#include <CType.h>
#include <conio.h>

#define KBS_UP          72
#define KBS_DOWN        80
#define KBS_LEFT        75
#define KBS_RIGHT       77

#define KBS_F1          59
#define KBS_F2          60
#define KBS_F3          61
#define KBS_F4          62
#define KBS_F5          63
#define KBS_F6          64
#define KBS_F7          65
#define KBS_F8          66
#define KBS_F9          67
#define KBS_F10         68
#define KBS_F11         69
#define KBS_F12         70

#define KBS_PGUP        73
#define KBS_PGDOWN      81

#define KBA_ESC         27
#define KBA_EOF         26
#define KBA_CR          13
#define KBA_LF          10
#define KBA_TAB         9
#define KBA_BACK        8
#define KBA_BREAK       3

#define KBCMD_CR        13
#define KBCMD_TAB       9
#define KBCMD_BACK      8


int16_t outCStr(int8_t *s)
{
    int16_t l;
    l = strlen(s);

    outString(s, l);
    return l;
}

void outString(int8_t *s, int16_t len)
{
    int8_t c, *p = NULL;

    if (len != 0)
        p = s + len;
    else
        return;

    while (p != s)
    {
        putCh(*s);
        s++;
    }
}

void putCh(int8_t c)
{
    asm mov al, c;
    asm mov ah, 0xE;
    asm mov bl, 0x7;
    asm int 0x10;
}

void writeCh(int8_t c, int16_t count)
{
    asm mov bx, 0;
    asm mov ah, 0xA;
    asm mov al, c;
    asm mov cx, count;
    asm int 0x10;
}

int8_t getCh()
{
    int8_t c;
    asm mov ax,0x0100;
    asm int 0x16;
    asm jnz retBack;
    asm mov ax,0000;
    asm int 0x16;
retBack:
    asm mov c, ax;
    return c;
}

int16_t getSC()
{
    int16_t r;
    asm mov ax,0x0100;
    asm int 0x16;
    asm jnz retBack;
    asm mov ax,0000;
    asm int 0x16;
retBack:
    asm mov r, ax;
    return r;

}

void setCursorPos(int8_t row, int8_t col)
{
    asm mov ax, 0x0200;
    asm mov dh, row;
    asm mov dl, col;
    asm mov bx, 0;
    asm int 0x10;
}

void getCursorPos(int8_t * row, int8_t * col)
{
    int8_t r, c;
    asm mov ax, 0x0300;
    asm mov bx, 0;
    asm int 0x10;
    asm mov r, dh;
    asm mov c, dl;
    *row = r, *col = c;
}

uint16_t getVideoMode()
{
    uint16_t r;
    asm mov ax, 0x0F00;
    asm int 0x10;
    asm mov r, ax;
    return r;
}

void clrscr()
{
    int16_t n;

    n = getVideoMode();
    n = n >> 8;

    setCursorPos(0, 0);
    writeCh(' ', n * 25);
}

int8_t * conInput(int16_t maxLen)
{
    int8_t row, col, width;
    int8_t cr, cl;
    static int8_t buf[256];
    uint16_t sc;
    int8_t c, s;
    uint16_t cmd;
    int16_t i = 0;

    if (maxLen <= 0 || maxLen > 255)
        {
        maxLen = 255;
        }

    getCursorPos(&row, &col);
    sc = getVideoMode();
    width = sc >> 8 & 0xFF;
    cr = row;
    cl = col;
    while (TRUE)
        {
        sc = getSC();
        c = sc & 0xFF;
        s = sc >> 8;

        cmd = 0;

        if (c == 0)
            {
            switch(s)
                {
                case KBS_LEFT:
                    cmd = KBCMD_BACK;
                    break;
                }
            }
        else
            {
            switch(c)
                {
                case KBA_CR:
                case KBA_LF:
                    c = 0, cmd = KBCMD_CR;
                    break;
                case KBA_BACK:
                    c = 0, cmd = KBCMD_BACK;
                    break;
                }
            if (c < 32 || c > 126)
                c = 0;
            }

        if (cmd != 0)
            {
            switch(cmd)
                {
                case KBCMD_CR:
                    outCStr(CRLF);
                    buf[i] = '\0';
                    return buf;
                case KBCMD_BACK:
                    if (i >  0)
                        {
                        getCursorPos(&row, &col);

                        if (col == 0)
                            cl = width - 1, cr = row - 1;
                        else
                            cl = col - 1, cr = row;

                        setCursorPos(cr, cl);

                        putCh(' ');

                        setCursorPos(cr, cl);

                        i--;
                        buf[i] = '\0';
                        }
                    break;
                default:
                    break;
                }
            }
        else
            {
            if (c != 0 && i < maxLen)
                {
                putCh(c);
                buf[i++] = c;
                }
            }
        }
}
